﻿#region Header

// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
//     <version>$Revision: 1471 $</version>
// </file>

#endregion Header

namespace ICSharpCode.TextEditor.Document
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// A stack of Span instances. Works like Stack&lt;Span&gt;, but can be cloned quickly
    /// because it is implemented as linked list.
    /// </summary>
    public sealed class SpanStack : ICloneable, IEnumerable<Span>
    {
        #region Fields

        StackNode top = null;

        #endregion Fields

        #region Properties

        public bool IsEmpty
        {
            get {
                return top == null;
            }
        }

        #endregion Properties

        #region Methods

        public SpanStack Clone()
        {
            SpanStack n = new SpanStack();
            n.top = this.top;
            return n;
        }

        public Enumerator GetEnumerator()
        {
            return new Enumerator(new StackNode(top, null));
        }

        object ICloneable.Clone()
        {
            return this.Clone();
        }

        IEnumerator<Span> IEnumerable<Span>.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        public Span Peek()
        {
            return top.Data;
        }

        public Span Pop()
        {
            Span s = top.Data;
            top = top.Previous;
            return s;
        }

        public void Push(Span s)
        {
            top = new StackNode(top, s);
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        #endregion Methods

        #region Nested Types

        public struct Enumerator : IEnumerator<Span>
        {
            #region Fields

            StackNode c;

            #endregion Fields

            #region Constructors

            internal Enumerator(StackNode node)
            {
                c = node;
            }

            #endregion Constructors

            #region Properties

            public Span Current
            {
                get {
                    return c.Data;
                }
            }

            object System.Collections.IEnumerator.Current
            {
                get {
                    return c.Data;
                }
            }

            #endregion Properties

            #region Methods

            public void Dispose()
            {
                c = null;
            }

            public bool MoveNext()
            {
                c = c.Previous;
                return c != null;
            }

            public void Reset()
            {
                throw new NotSupportedException();
            }

            #endregion Methods
        }

        internal sealed class StackNode
        {
            #region Fields

            public readonly Span Data;
            public readonly StackNode Previous;

            #endregion Fields

            #region Constructors

            public StackNode(StackNode previous, Span data)
            {
                this.Previous = previous;
                this.Data = data;
            }

            #endregion Constructors
        }

        #endregion Nested Types
    }
}